﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using S3.DataModel;
using S3.Properties;
using S3.Biz;
using S3.Common;
using ComboBox = System.Windows.Forms.ComboBox;

namespace S3
{
    public partial class ViewOrderDetails : S3FormBase
    {
        private readonly DateTime _endTime;
        private bool _isChanged;
        private DateTime _startTime;

        public ViewOrderDetails(string strDeskName)
        {
            _endTime = DateTime.Now;
            InitializeComponent();
            gridGameMoneyConclusion.AutoGenerateColumns = false;
            gridGameData.AutoGenerateColumns = false;
            gridServiceDetails.AutoGenerateColumns = false;
            DisplayDeskInfo(strDeskName);

            DisplayGameData(strDeskName);

            DisplayServiceData(strDeskName);

            GetPlayingDesk();

            txtCustomerGave.Focus();
            txtCustomerGave.SelectAll();
        }

        #region DisplayDeskInfo

        private void DisplayDeskInfo(string strDeskName)
        {
            //Show thong tin
            lblDeskName.Text = strDeskName;

            using (var dailyEntryManager = new DailyTimingEntryManager())
            {
                DailyTimingEntry entry = dailyEntryManager.GetOnePlaying(strDeskName);

                decimal decGameMoney = 0;
                decimal decAddedItemMoney = 0;
                decimal decPaidMoney = 0;
                decimal decTotal = 0;

                if (entry != null)
                {
                    //Total Fund
                    dailyEntryManager.CalTotalMoneyByDesk(strDeskName, ref decGameMoney, ref decTotal);

                    txtGameMoney.Text = Utils.StringFormatMoney(decGameMoney);
                    txtAdditionalItemMoney.Text = Utils.StringFormatMoney(decAddedItemMoney);
                    txtPaidMoney.Text = Utils.StringFormatMoney(decPaidMoney);
                    string total = Utils.StringFormatMoney(decTotal);
                    txtTotal.Text = total;
                    txtBalance.Text = decTotal > 0 ? "-" + total : total;

                    if (txtBalance.Text != string.Empty && txtBalance.Text != "0")
                    {
                        comboPlayingMachineList.Enabled = true;
                        btnTransferMoney.Enabled = true;
                    }

                    lblTotalMoneyByWord.Text = Utils.DocSo(decTotal);

                    txtRemark.Text = entry.Notes;

                    _startTime = entry.StartTime;
                }
            }
        }

        #endregion

        #region DisplayGameData

        private void DisplayGameData(string deskName)
        {
            using (var dailyEntryManager = new DailyTimingEntryManager())
            {
                //Log records
                IQueryable<DailyTimingEntry> dailyEntries = dailyEntryManager.GetWatingFinishEntriesByDesk(deskName);
                var machineMoneyList = new List<ExtendDailyEntry>();

                foreach (DailyTimingEntry entry in dailyEntries)
                {
                    var machineMoney = new ExtendDailyEntry();
                    machineMoney.Type = entry.Type;

                    machineMoney.StartTime = string.Format(Constants.Format_Date_Time, entry.StartTime);

                    DateTime endDate = entry.EndTime.HasValue ? entry.EndTime.Value : DateTime.Now;
                    machineMoney.EndTime = string.Format(Constants.Format_Date_Time, endDate);

                    decimal playedMinutes = 0;
                    if (entry.EndTime.HasValue)
                    {
                        playedMinutes = Convert.ToDecimal(entry.EndTime.Value.Subtract(entry.StartTime).TotalMinutes);
                    }
                    else
                    {
                        playedMinutes = Convert.ToDecimal(DateTime.Now.Subtract(entry.StartTime).TotalMinutes);
                    }

                    decimal playedTimeRound = Math.Floor(playedMinutes);

                    machineMoney.TotalTime = playedTimeRound == 0 ? "1" : playedTimeRound + "";

                    machineMoneyList.Add(machineMoney);
                }

                gridGameData.DataSource = machineMoneyList;

                //Display summary list
                string[] kindOfMachines = Utils.KindOfMachinesList();

                using (DailyTimingEntryManager block = new DailyTimingEntryManager())
                {
                    var mmList = new List<ExtendDailyEntry>();

                    foreach (string machine in kindOfMachines)
                    {
                        decimal totalMinutes = 0;

                        var mm = new ExtendDailyEntry();
                        mm.Type = machine;
                        IQueryable<DailyTimingEntry> sameKindList =
                            dailyEntries.Where(a => a.Type.ToLower() == machine.ToLower());
                        foreach (DailyTimingEntry entry in sameKindList)
                        {
                            if (entry.EndTime.HasValue)
                            {
                                totalMinutes = totalMinutes +
                                               Convert.ToDecimal(
                                                   entry.EndTime.Value.Subtract(entry.StartTime).TotalMinutes);
                            }
                            else
                            {
                                totalMinutes = totalMinutes +
                                               Convert.ToDecimal(DateTime.Now.Subtract(entry.StartTime).TotalMinutes);
                            }
                        }


                        if (totalMinutes > 0)
                        {
                            decimal playedTimeRound = Math.Floor(totalMinutes);

                            mm.TotalTime = playedTimeRound == 0 ? "1" : playedTimeRound + "";

                            mm.TotalMoney =
                                Utils.StringFormatMoney(block.CalcGameMoneyByBlock(totalMinutes, machine, null, null,
                                                                                   null, null));

                            mmList.Add(mm);
                        }
                    }

                    gridGameMoneyConclusion.DataSource = mmList;
                }
            }
        }

        #endregion

        #region DisplayServiceData

        private void DisplayServiceData(string deskName)
        {
            using (var additionalItemUnitPriceManager = new GoodsStoreManager())
            {
                var itemsList =
                    additionalItemUnitPriceManager.GetAllAvaiable().Select(a => new {a.ItemName, a.UnitPrice});

                using (var dailyAdditionalItemEntryManager = new DailyItemEntryManager())
                {
                    var entries =
                        dailyAdditionalItemEntryManager.GetUnpaidByDesk(deskName).Select(
                            a => new {a.ItemName, a.Quantity});
                    var servicesList = new List<ExtendService>();

                    foreach (var entry in entries)
                    {
                        if (entry.Quantity > 0)
                        {
                            var service = new ExtendService();
                            service.ItemName = entry.ItemName;

                            foreach (var item in itemsList)
                            {
                                if (entry.ItemName.ToLower() == item.ItemName.ToLower())
                                {
                                    decimal qty = entry.Quantity;
                                    service.Quantity = qty;
                                    decimal unitPrice = item.UnitPrice;
                                    service.UnitPrice = Utils.StringFormatMoney(unitPrice);
                                    decimal money = qty*unitPrice;
                                    service.TotalServiceMoney = Utils.StringFormatMoney(money);
                                }
                            }

                            servicesList.Add(service);
                        }
                    }

                    gridServiceDetails.DataSource = servicesList.OrderBy(a => a.ItemName).ToList();
                }
            }
        }

        #endregion

        /// <summary>
        /// Display Desk Information
        /// </summary>
        /// <param name="strDeskName"></param>

        /// <summary>
        /// Hien thi du lieu ve choi game
        /// </summary>
        /// <param name="deskName"></param>

        /// <summary>
        /// Hien thi du lieu dich vu goi them
        /// </summary>
        /// <param name="deskName"></param>

        private void txtCustomerGave_Enter(object sender, EventArgs e)
        {
            txtCustomerGave_Leave(sender, e);
        }

        private void txtCustomerGave_Leave(object sender, EventArgs e)
        {
            decimal custGave = 0;
            if (decimal.TryParse(txtCustomerGave.Text.Trim(), out custGave))
            {
                decimal mustPay = Convert.ToDecimal(txtTotal.Text);

                //tu dong them hang nghin vao so tien khach dua
                if (custGave < 1000)
                {
                    custGave = custGave*1000;
                }

                decimal remaining = custGave - mustPay;

                txtBalance.Text = Utils.StringFormatMoney(remaining);

                if (remaining != 0)
                {
                    comboPlayingMachineList.Enabled = true;
                    btnTransferMoney.Enabled = true;
                }
                else
                {
                    comboPlayingMachineList.Enabled = false;
                    btnTransferMoney.Enabled = false;
                }

                txtCustomerGave.Text = Utils.StringFormatMoney(custGave);
            }
            else
            {
                txtCustomerGave.Text = "0";
                decimal decTotal = Convert.ToDecimal(txtTotal.Text);
                txtBalance.Text = decTotal > 0
                                      ? "-" + Utils.StringFormatMoney(decTotal)
                                      : Utils.StringFormatMoney(decTotal);
            }
        }

        private void txtCustomerGave_KeyPress(object sender, KeyPressEventArgs e)
        {
            //Neu an Enter
            if (e.KeyChar == Convert.ToChar(13))
            {
                txtCustomerGave_Leave(sender, e);
            }
        }

        //Get Playing desk
        private void GetPlayingDesk()
        {
            using (var dailyEntryManager = new DailyTimingEntryManager())
            {
                IQueryable<DailyTimingEntry> dailyEntryPlayingListRaw =
                    dailyEntryManager.GetPlayingDesks().Where(a => a.TimingServiceName.ToLower() != lblDeskName.Text.ToLower());

                if (dailyEntryPlayingListRaw != null)
                {
                    IQueryable<string> dailyEntryPlayingList =
                        dailyEntryPlayingListRaw.OrderBy(a => a.TimingServiceName).Select(a => a.TimingServiceName);

                    comboPlayingMachineList.Items.Add("");

                    if (dailyEntryPlayingList.Count() > 0)
                    {
                        foreach (string item in dailyEntryPlayingList)
                        {
                            comboPlayingMachineList.Items.Add(item);
                        }
                    }
                    else
                    {
                        comboPlayingMachineList.Enabled = false;
                        btnTransferMoney.Enabled = false;
                    }
                }
            }
        }

        private void gridServiceDetails_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            object serviceName = gridServiceDetails.Rows[e.RowIndex].Cells[0].Value;
            int qty = Convert.ToInt32(gridServiceDetails.Rows[e.RowIndex].Cells[1].Value);

            if (serviceName != null)
            {
                //Update total money of this record
                decimal unitPrice = Convert.ToDecimal(gridServiceDetails.Rows[e.RowIndex].Cells[2].Value);
                decimal money = qty*unitPrice;
                gridServiceDetails.Rows[e.RowIndex].Cells[3].Value = Utils.StringFormatMoney(money);

                //Dua dich vu nay vao bang Additional Item
                using (var dailyAdditionalItemEntryManager = new DailyItemEntryManager())
                {
                    var dailyAdditionalItemEntry = new DailyItemEntry
                                                       {
                                                           ItemName = serviceName + "",
                                                           TimingServiceName = lblDeskName.Text,
                                                           Quantity = qty,
                                                           Amount = money
                                                       };

                    dailyAdditionalItemEntryManager.Save(dailyAdditionalItemEntry);
                }

                //re-calculate money
                DisplayDeskInfo(lblDeskName.Text);

                _isChanged = true;
            }
        }

        private void btnFinish_Click(object sender, EventArgs e)
        {
            try
            {
                using (var dailyEntryManager = new DailyTimingEntryManager())
                {
                    dailyEntryManager.StopPlaying(lblDeskName.Text, Convert.ToDecimal(txtAdditionalItemMoney.Text),
                                                  Convert.ToDecimal(txtTotal.Text), _endTime);
                }

                _isChanged = true;

                PrintDataObject data = CollectDataToPrint();
                Utils.DoPrint(data);

                //Close this form
                Close();
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show("Error: " + ex.Message);
            }
        }

        /// <summary>
        /// Close form if click ESC
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>

        private void gridGameData_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            //DataGridViewComboBoxColumn comboBoxColumn = (DataGridViewComboBoxColumn)gridGameData.Columns[0];

            //if (gridGameData.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)
            //{
            //    if (!comboBoxColumn.Items.Contains(e.FormattedValue))
            //    {
            //        comboBoxColumn.Items.Add(e.FormattedValue);
            //    }
            //}

            var cell = gridGameData.CurrentCell as DataGridViewComboBoxCell;

            if (cell != null &&
                !cell.Items.Contains(e.FormattedValue))
            {
                // Insert the new value into position 0
                // in the item collection of the cell
                cell.Items.Insert(0, e.FormattedValue);
                // When setting the Value of the cell, the  
                // string is not shown until it has been
                // comitted. The code below will make sure 
                // it is committed directly.
                if (gridGameData.IsCurrentCellDirty)
                {
                    // Ensure the inserted value will 
                    // be shown directly.
                    // First tell the DataGridView to commit 
                    // itself using the Commit context...
                    gridGameData.CommitEdit(DataGridViewDataErrorContexts.Commit);
                }
                // ...then set the Value that needs 
                // to be committed in order to be displayed directly.
                cell.Value = cell.Items[0];
            }
        }

        private void gridGameData_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (string.IsNullOrEmpty(lblDeskName.Text)) return;

            var comboBoxColumn = (DataGridViewComboBoxColumn) gridGameData.Columns[0];

            if (gridGameData.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)
            {
                var cb = (ComboBox) e.Control;
                if (cb != null)
                {
                    var deskConfigurationManager = new TimingServiceConfigurationManager();
                    cb.DataSource = deskConfigurationManager.GetKindOfMachineByDesk(lblDeskName.Text);
                    cb.DisplayMember = "Type";
                }
            }
        }

        private void gridGameData_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            throw new Exception("Error in grid Game data!");
        }

        private void btnUpdateRemark_Click(object sender, EventArgs e)
        {
            try
            {
                using (var dailyEntryManager = new DailyTimingEntryManager())
                {
                    dailyEntryManager.UpdateNotes(lblDeskName.Text, txtRemark.Text.Trim(), true);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private void btnTransferMoney_Click(object sender, EventArgs e)
        {
            string currentDesk = lblDeskName.Text;
            string destinationDesk = comboPlayingMachineList.Text;
            decimal money = decimal.Parse(txtBalance.Text.Trim());

            if (!string.IsNullOrEmpty(currentDesk) && !string.IsNullOrEmpty(destinationDesk) && money != 0)
            {
                try
                {
                    string strMoney = Utils.StringFormatMoney(money);
                    const string msgRaw = "Bạn muốn chuyển {0} đồng sang {1}?";

                    string msg = string.Format(msgRaw, strMoney, destinationDesk);

                    DialogResult dialogResult = XtraMessageBox.Show(msg, "Chú ý", MessageBoxButtons.YesNo);
                    if (dialogResult == DialogResult.Yes)
                    {
                        using (var dailyEntryManager = new DailyTimingEntryManager())
                        {
                            dailyEntryManager.TransferMoney(currentDesk, destinationDesk, money);

                            XtraMessageBox.Show("Đã chuyển xong !");

                            //Update remark to current machine
                            //string msgRaw2 = "- [" + string.Format(Constants.Format_Date_Time, DateTime.Now) + "] " + "Đã chuyển {0} đồng sang {1}.";
                            //string msg2 = string.Format(msgRaw2, strMoney, destinationDesk);

                            //dailyEntryManager.UpdateRemark(currentDesk, msg2, false);
                        }
                    }

                    //Ket thuc
                    btnFinish_Click(sender, e);
                }
                catch (Exception)
                {
                    XtraMessageBox.Show("Lỗi trong quá trình chuyển tiền !");
                }
            }
        }


        private void txtBalance_Leave(object sender, EventArgs e)
        {
            decimal output = 0;
            if (decimal.TryParse(txtBalance.Text, out output))
            {
                txtBalance.Text = Utils.StringFormatMoney(output);
            }
            else
            {
                txtBalance.Text = "0";
            }
        }

        

        private void ViewOrderDetails_FormClosing(object sender, FormClosingEventArgs e)
        {
            
        }

        #region Print

        private void btnPrint_Click(object sender, EventArgs e)
        {
        }

        private PrintDataObject CollectDataToPrint()
        {
            var printDataObject = new PrintDataObject();
            printDataObject.CustomerID = "";
            printDataObject.CustomerName = "";
            printDataObject.TimingServiceName = lblDeskName.Text;
            printDataObject.InvoiceID = Utils.InvoiceNoGenerating();
            printDataObject.StartTime = string.Format(Constants.Format_Date_Time, _startTime);
            printDataObject.EndTime = string.Format(Constants.Format_Date_Time, _endTime);
            ;
            printDataObject.Paid = txtPaidMoney.Text;

            var listData = new List<PrintSoldItems>();

            //Tien game
            foreach (DataGridViewRow item in gridGameMoneyConclusion.Rows)
            {
                var data = new PrintSoldItems
                               {
                                   Name = item.Cells[0].Value.ToString(),
                                   Qty = item.Cells[1].Value + " phút",
                                   Price = "",
                                   SubTotal = item.Cells[2].Value.ToString()
                               };

                listData.Add(data);
            }

            //Tien dich vu
            foreach (DataGridViewRow item in gridServiceDetails.Rows)
            {
                var data = new PrintSoldItems
                               {
                                   Name = item.Cells[0].Value.ToString(),
                                   Qty = item.Cells[1].Value.ToString(),
                                   Price = item.Cells[2].Value.ToString(),
                                   SubTotal = item.Cells[3].Value.ToString()
                               };

                listData.Add(data);
            }

            printDataObject.TotalMoney = txtTotal.Text;


            printDataObject.Discount = "";
            printDataObject.ListPrintSoldItems = listData;

            return printDataObject;
        }
        
        #endregion

        #region ProcessCmdKey

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            try
            {
                if (msg.WParam.ToInt32() == (int) Keys.Escape)
                {
                    Close();
                }
                else
                {
                    return base.ProcessCmdKey(ref msg, keyData);
                }
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Key Overrided Events Error:" + Ex.Message);
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }

        #endregion
    }
}